{ 
	open Parser
}

rule token = parse
  [' ' '\t' '\r' '\n'] { token lexbuf } (* Whitespace *)
  | "/*"     { block_comment lexbuf }           (* Comments *)
  | "//"     { line_comment lexbuf }
  (* Tokens *)
  | '('      { LPAREN }
  | ')'      { RPAREN }
  | '{'      { LBRACE }
  | '}'      { RBRACE }
  | '['      { LSBRACE }
  | ']'      { RSBRACE }
  | ';'      { SEMI }
  | ','      { COMMA }
  | "++"     { PLUSPLUS}
  | "--"     { MINUSMINUS}
  | "=="     { EQ }
  | "!="     { NE }
  | "<="     { LE }
  | ">="     { GE }
  | "&&"     { AND }
  | "||"     { OR }
  | '+'      { PLUS }
  | '-'      { MINUS }
  | '*'      { TIMES }
  | '/'      { DIVIDE }
  | '%'      { MOD }
  | "+="      { PLUS_ASSIGN }
  | "-="      { MINUS_ASSIGN }
  | "*="      { TIMES_ASSIGN }
  | "/="      { DIVIDE_ASSIGN }
  | "%="      { MOD_ASSIGN }
  | '='      { ASSIGN }
  | '<'      { LT }
  | '>'      { GT }
  | '!'      { NOT }
  | "."      { DOT }
  (* reserved keywords *)
	(* primitive data types *)
  | "int"    { INT }
  | "double" { DOUBLE }
  | "string" { STRING } (* XINAN: to use C++ string type *)
  | "list"   { LIST }   (* to use C++ STL vector *)
  | "point"  { POINT }  (* XINAN: point with a radius *)
  | "shape"  { SHAPE }  (* Polygon *)
  | "image"  { IMAGE } (* XINAN: probably a file descriptor pointed to a bitmap image *)
  | "struct" { STRUCT } (* Same as C *)
    (* keywords for control flow *)
  | "if"     { IF }
  | "else"   { ELSE }
  | "for"    { FOR }
  | "return" { RETURN }
  | "break"  { BREAK }
(* constant *)
  | ['0'-'9']+ as lxm { CONST_INT(int_of_string lxm) }
  | ['-']? ['0'-'9']+ '.' ['0'-'9']+ ('e' ['-']? ['0'-'9']+)? as lxm { CONST_DBL(float_of_string lxm) }
  | '"'  { const_string "" lexbuf }
  | ['a'-'z' 'A'-'Z' ]['a'-'z' 'A'-'Z' '0'-'9' '_']* as lxm { ID(lxm) }
  | eof { EOF }
  | ['.']['0'-'9']* as float { raise (Failure("No support for float type " ^ float)) }
  | _ as char { raise (Failure("illegal character " ^ Char.escaped char)) }                                         
and block_comment = parse
    "*/" { token lexbuf }
	| _  { block_comment lexbuf } 
and line_comment = parse
	"\n" { token lexbuf }
	| _  { line_comment lexbuf }
and const_string temp_str = parse
(* XINAN: not sure whether this will work *)
	[^ '"' '\']*  as lxm { const_string (temp_str ^ lxm) lexbuf	}
	|'\' { escape_character temp_str lexbuf }
	|'"' { CONST_STR(temp_str) }
and escape_character temp_str = parse
	['\' '"'] as lxm { const_string (temp_str ^ lxm) lexbuf }
	|'n' { const_string (temp_str ^ "\n") lexbuf }
	|'r' { const_string (temp_str ^ "\r") lexbuf }
	|'t' { const_string (temp_str ^ "\t") lexbuf }
	| _ {const_string temp_str lexbuf}
